<?php
	/**
	 * upload.php -  upload single or multiple files
	 *
	 * @param: $CFG = array()
	 *
	 * @author: swingcoder@msn.com
	 * @copyright: 2006-2-28
	 * @modified: 2009-11-27
	 */

	class upload
	{
		var $ERRMSG;
		var $upfiles;
		var $CFG = array(
			"DEST_DIR"=>"",							//destination diretory
			"IS_OVERWRITE"=>1,					//0 false,1 true
			"CREATE_DIR"=>1,						//0 no,1 yes
			"FILE_NAME_STYLE"=>"datetime",	//naming style:[empty for no change]|date|datetime|random|.others will same as input
			"FILE_TYPE"=>"gif,jpg,png",			//file extension check. e.g gif,jpg,png...
			"FILE_MAX_SIZE"=>"2097152",		//max file size,default 2m
			"MUST_UPLOAD_FILE_INDEX"=>""//must upload file sequence e.g. 1,2,3,5...,empty for all,0 for null
		);

		/**
		 * initlization
		 *
		 * @param array $CFG
		 * @return mixed
		 */
		function upload()
		{
		}


		/**
		 * init cfg
		 * detail description
		 * @param array cfg('DEST_DIR' => '', 'FILE_TYPE' => 'jpg,gif,png',  'MUST_UPLOAD_FILE_INDEX' => 1 )
		 * @return boolean
		 */
		function init_cfg( $CFG )
		{
			if( empty( $CFG ) || ! is_array( $CFG ) || count( $CFG ) <= 0 )
			{
				$this->ERRMSG = "class upload: [1]wrong config argument.";
				return false;
			}

			foreach ( $CFG as $index => $value )
			{
				if ( ! is_array( $value ) || count( $value ) <= 0 )
				{
					$this->ERRMSG = "class upload: [2]wrong config argument.";
					return false;
				}
				else
				{
					foreach ( $value as $index2 => $value2 )
					{
						if( $index2 == 'DEST_DIR' && ! preg_match( '/\/$/', $value2 ) )
						{
							$value2 .= "/";
						}
						if( $index2 == 'FILE_TYPE' )
						{
							$value2 = strtolower( $value2 );
						}
						$CFG[$index][$index2] = $value2;
					}
					$CFG[$index] = array_merge( $this->CFG, $CFG[$index] );
				}
			}

			$this->CFG = $CFG;
		}

		/**
		 * upload file
		 *
		 * @return boolean
		 */
		function do_upload()
		{
			if( $this->do_check() )
			{
				$upload_files = array();

				foreach ( $this->upfiles as $upload_field => $file_list )
				{
					if ( $file_list['name'][0] == '' )
					{
						continue;
					}
					foreach ( $file_list['name'] as $idx => $file_name )
					{
						$new_file_name = $this->gen_new_filename( $file_name, $this->CFG[$upload_field]["FILE_NAME_STYLE"], $idx );
						$dest_new_file = '';
						$dest_new_file = $this->CFG[$upload_field]["DEST_DIR"] . $new_file_name;

						if( is_uploaded_file( $file_list['tmp_name'][$idx] )
							&& move_uploaded_file( $file_list['tmp_name'][$idx], $dest_new_file ) )
						{
							$upload_files[$upload_field][] = $dest_new_file;
						}
					}
				}

				return $upload_files;
			}
			else
			{
				return false;
			}

			return true;
		}

		/**
		 * do_check
		 *check uploaded files arrtibutes
		 * @return boolean
		 */
		function do_check()
		{
			if( empty( $this->CFG ) || ! is_array( $this->CFG ) || count( $this->CFG ) <= 0 )
			{
				$this->ERRMSG = "class upload: [3]wrong config argument.";
				return false;
			}

			if ( ! isset( $_FILES ) || ! is_array( $_FILES ) || count( $_FILES ) <= 0 )
			{
				$this->ERRMSG = 'class upload: nothing to upload.';
				return false;
			}

			$this->upfiles = $_FILES;

			//文件属性全部转成数据格式
			foreach ( $this->upfiles as $idx => $files )
			{
				foreach ( $files as $field_name => $field_value )
				{
					if ( ! is_array( $field_value ) )
					{
						$this->upfiles[$idx][$field_name] = array();
						$this->upfiles[$idx][$field_name][] = $field_value;
					}
				}
				//检查相应的文件配置参数有没有定义
				$matched = false;
				foreach ( $this->CFG as $cindex => $cvalue )
				{
					if ( $cindex === $idx )
					{
						$matched = true;
						break;
					}
				}
				if ( $matched === false )
				{
					$this->ERRMSG = 'class upload: [4]wrong config argument.';
					return false;
				}
			}

			//判断文件属性
			foreach ( $this->upfiles as $idx => $files )
			{
				foreach ( $files as $field_name => $field_value )
				{
					foreach ( $field_value as $index => $value )
					{
						if ( ! isset( $this->CFG[$idx] ) )
						{
							$this->ERRMSG = 'class upload: [5]wrong config argument."';
							return false;
						}
						if ( ! $this->{'check_' . $field_name}( $value, $this->CFG[$idx], $index ) )
						{
							return false;
						}
					}
				}
			}

			//检查传递过来的配置
			foreach ( $this->CFG as $index => $value )
			{
				if ( ! is_dir( $value['DEST_DIR'] ) )
				{
					if ( ! mkdir( $value['DEST_DIR'], 0755, true ) )
					{
						$this->ERRMSG = 'class upload: 创建文件夹失败' . $value['DEST_DIR'];
						return false;
					}
				}
				if ( ! is_writable( $value['DEST_DIR'] ) )
				{
					$this->ERRMSG = 'class upload: 文件夹不可写' . $value['DEST_DIR'];
					return false;
				}
			}

			return true;
		}

		/**
		 * 检查文件名
		 * detail description
		 * @param string value
		 * @param array cfg
		 * @return boolean
		 */
		function check_name( $value, $cfg, $index )
		{
			$success = false;
			if ( ! empty( $value ) )
			{
				$success = preg_match( '/[a-zA-Z0-9_\.\-\x7f-\xff]/i', $value );
				$pattern = str_replace( ',', '|', $cfg['FILE_TYPE'] );
				$info = pathinfo( $value );
				$success = preg_match( '/^(' . $pattern . ')$/i',  $info['extension'] );
			}
			else
			{
				$pattern = str_replace( ',', '|', $cfg['MUST_UPLOAD_FILE_INDEX'] );
				if ( ! preg_match( '/^(' . $pattern . ')$/i',  ( $index + 1 ) ) )
				{
					$success = true;
				}
			}

			return $success;
		}


		/**
		 * 检查文件类型
		 * 此处不作是否强制要上传判断,依赖check_name
		 * @param string $value
		 * @param array $cfg
		 * @param interger $index
		 * @return boolean
		 */
		function check_type(  $value, $cfg, $index )
		{
			$success = false;

			if ( $value != '' )
			{
				$pattern = 'image\/gif|image\/jpeg|image\/png|text\/plain|text\/html|image\/pjpeg';
				if ( preg_match( '/^(' . $pattern . ')$/i',  $value ) )
				{
					$success = true;
				}
				else
				{
					$this->ERRMSG = '文件类型不合法' . $value;
				}
			}
			else
			{
				$success = true;
			}

			return $success;
		}


		/**
		 * 检查临时文件名
		 * detail description
		 * @param string value
		 * @param array cfg
		 * @return boolean
		 */
		function check_tmp_name(  $value, $cfg, $index )
		{
			return true;
		}


		/**
		 * 检查文件大小
		 * detail description
		 * @param string value
		 * @param array cfg
		 * @return boolean
		 */
		function check_size(  $value, $cfg, $index )
		{
			$success = false;

			if ( $value > $cfg['FILE_MAX_SIZE'] )
			{
				$this->ERRMSG = '超过上传大小限制' . $value;
			}
			else
			{
				$success = true;
			}
			return $success;
		}


		/**
		 * 检查上传错误
		 * detail description
		 * @param string value
		 * @param array cfg
		 * @return boolean
		 */
		function check_error(  $value, $cfg, $index )
		{
			$success = false;

			switch ( $value )
			{
				case UPLOAD_ERR_OK :
					$success = true;
					break;

				case UPLOAD_ERR_INI_SIZE:
					$this->ERRMSG = 'The uploaded file exceeds the upload_max_filesize directive in php.ini';
					break;

				case UPLOAD_ERR_FORM_SIZE:
					$this->ERRMSG = 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
					break;

				case UPLOAD_ERR_PARTIAL:
					$this->ERRMSG = 'The uploaded file was only partially uploaded. ';
					break;

				case UPLOAD_ERR_NO_FILE:
					$success = true;
					break;

				case UPLOAD_ERR_NO_TMP_DIR:
					$this->ERRMSG = 'Missing a temporary folder';
					break;

				case UPLOAD_ERR_CANT_WRITE:
					$this->ERRMSG = 'Failed to write file to disk';
					break;

				case UPLOAD_ERR_EXTENSION:
					$this->ERRMSG = 'File upload stopped by extension';
					break;

				default:
			}

			return $success;
		}

		/**
		 * 生成新文件名
		 * detail description
		 * @param string $file_name
		 * @param string $name_style
		 * @param integer $index
		 * @return boolean
		 */
		function gen_new_filename( $file_name, $name_style, $key )
		{
			$info = pathinfo( $file_name );

			switch($name_style)
			{
				case "":
					$new_file_name = $file_name;
				break;

				case "date":
					$date = date("Ymd");
					$new_file_name = $date . '.' . $info['extension'];
				break;

				case "datetime";
					list($usec, $sec) = explode(' ', microtime());
					(float) $sec + ((float) $usec * 100000);
					$date = date("YmdHis").rand(1,$sec);
					$new_file_name = $date . '.' . $info['extension'];
				break;

				case "random";
					list($usec, $sec) = explode(' ', microtime());
					(float) $sec + ((float) $usec * 100000);
					$random = md5(crypt($sec));
					$new_file_name = $random .  '.' . $info['extension'];
				break;

				default:
					$new_file_name = $name_style;
			}

			return $new_file_name;
		}


		/**
		 * 加水印
		 * detail description
		 * @param string src_file 原文件
		 * @param string watermark_file 水印文件路径
		 * @param string outfile 保存文件路径
		 * @param string location 坐标,up-left|up-middle|up-right|middle-left|center|
		 *	middle-right|bottom-left|bottom-middle|bottom-right
		 * @param string transparent 透明度
		 * @return array( 'success' => false, 'message' => '' )
		 */
		function add_watermark( $src_file, $watermark_file, $outfile = '', $location = 'bottom-right', $transparent = 75 )
		{
			$return = array( 'success' => false, 'message' => '' );

			if ( $outfile == '' )
			{
				$outfile = $src_file;
			}
			if ( ! function_exists( 'imagecreatefromjpeg' ) )
			{
				$return['message'] = 'GD库不存在';
				return $return;
			}
			if ( empty( $src_file ) || empty( $watermark_file ) )
			{
				$return['message'] = '参数错误';
				return $return;
			}
			if ( ! is_file( $src_file ) || ! is_file( $watermark_file ) )
			{
				$return['message'] = '原文件或水印文件不存在';
				return $return;
			}
			if ( ! is_readable( $src_file ) || ! is_readable( $watermark_file ) )
			{
				$return['message'] = '原文件或水印文件不可读取';
				return $return;
			}

			$src_fileinfo = pathinfo( $src_file );
			$watermark_fileinfo = pathinfo( $watermark_file );
			$src_imgsize = getimagesize( $src_file );
			$watermark_imgsize = getimagesize( $watermark_file );

			if ( $src_fileinfo['extension'] == 'jpg' || $src_fileinfo['extension'] == 'jpeg' )
			{
				$src_img = imagecreatefromjpeg( $src_file );
			}
			else if ( $src_fileinfo['extension'] == 'gif' )
			{
				$src_img = imagecreatefromgif( $src_file );
			}
			else if ( $src_fileinfo['extension'] == 'png' )
			{
				$src_img = imagecreatefrompng( $src_file );
			}
			else
			{
				$return['message'] = '不支持的源文件格式';
				return $return;
			}

			if ( $watermark_fileinfo['extension'] == 'jpg' || $watermark_fileinfo['extension'] == 'jpeg' )
			{
				$watermark_img = imagecreatefromjpeg( $watermark_file );
			}
			else if ( $watermark_fileinfo['extension'] == 'gif' )
			{
				$watermark_img = imagecreatefromgif( $watermark_file );
			}
			else if ( $watermark_fileinfo['extension'] == 'png' )
			{
				$watermark_img = imagecreatefrompng( $watermark_file );
			}
			else
			{
				$return['message'] = '不支持的水印文件格式';
				return $return;
			}

			//计算水印坐标
			$watermark_loc = array( 'x' => 0, 'y' => 0 );
			$padding = 10;

			if ( $location == 'up-left' )
			{
				$watermark_loc['x'] = $padding;
				$watermark_loc['y'] = $padding;
			}
			else if ( $location == 'up-middle' )
			{
				$watermark_loc['x'] = ( $src_imgsize[0] / 2 - $watermark_imgsize[0] / 2 );
				$watermark_loc['y'] = $padding;
			}
			else if ( $location == 'up-right' )
			{
				$watermark_loc['x'] = ( $src_imgsize[0] - $watermark_imgsize[0] - $padding );
				$watermark_loc['y'] = $padding;
			}
			else if ( $location == 'middle-left' )
			{
				$watermark_loc['x'] = $padding;
				$watermark_loc['y'] = ( $src_imgsize[1] / 2 - $watermark_imgsize[1] / 2 );
			}
			else if ( $location == 'center' )
			{
				$watermark_loc['x'] = ( $src_imgsize[0] / 2 - $watermark_imgsize[0] / 2 );
				$watermark_loc['y'] = ( $src_imgsize[1] / 2 - $watermark_imgsize[1] / 2 );
			}
			else if ( $location == 'middle-right' )
			{
				$watermark_loc['x'] = ( $src_imgsize[0] - $watermark_imgsize[0] - $padding );
				$watermark_loc['y'] = ( $src_imgsize[1] / 2 - $watermark_imgsize[1] / 2);
			}
			else if ( $location == 'bottom-left' )
			{
				$watermark_loc['x'] = $padding;
				$watermark_loc['y'] = $src_imgsize[1] - $padding - $watermark_imgsize[1];
			}
			else if ( $location == 'bottom-middle' )
			{
				$watermark_loc['x'] = ( $src_imgsize[0] / 2 - $watermark_imgsize[0] / 2 );
				$watermark_loc['y'] = $src_imgsize[1] - $padding - $watermark_imgsize[1];
			}
			else if ( $location == 'bottom-right' )
			{
				$watermark_loc['x'] = $src_imgsize[0] - $padding - $watermark_imgsize[0];
				$watermark_loc['y'] = $src_imgsize[1] - $padding - $watermark_imgsize[1];
			}
			else
			{
				$watermark_loc['x'] = $src_imgsize[0] - $padding - $watermark_imgsize[0];
				$watermark_loc['y'] = $src_imgsize[1] - $padding - $watermark_imgsize[1];
			}

			imagecopymerge( $src_img, $watermark_img, $watermark_loc['x'], $watermark_loc['y'], 0, 0, $watermark_imgsize[0], $watermark_imgsize[1], $transparent );

			if ( $src_fileinfo['extension'] == 'jpg' || $src_fileinfo['extension'] == 'jpeg' )
			{
				imagejpeg( $src_img, $outfile );
			}
			else if ( $src_fileinfo['extension'] == 'gif' )
			{
				imagegif( $src_img, $outfile );
			}
			else if ( $src_fileinfo['extension'] == 'png' )
			{
				imagepng( $src_img, $outfile );
			}

			imagedestroy($src_img);
			imagedestroy($watermark_img);

			$return['success'] = true;

			return $return;
		}
	}
?>